package cn.dansj.common.utils.json;

import cn.dansj.common.utils.enums.GlobalEnv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

public enum Feature implements Serializable {
    /**
     * 序列化和反序列化时直接操作字段，包含私有字段
     */
    FILED_BASE(Usage.All),
    /**
     * 序列化时包含为null的字段
     */
    INCLUDE_NULL_FIELDS(Usage.Serialization),
    /**
     * 序列化时把date转换成timestamp
     */
    USE_TIMESTAMPS(Usage.Serialization),
    /**
     * 序列化时格式化打印
     */
    PRETTY_PRINT(Usage.Serialization),
    /**
     * 反序列化时无视命名规则和大小写进行字段匹配
     */
    SMART_MATCH(Usage.Deserialization),
    /**
     * 序列化时值用大写的字符串
     */
    ENUM_UPPERCASE_STRING(Usage.Serialization),
    /**
     * 序列化时值用序列代替
     */
    ENUM_INDEX(Usage.Serialization),
    /**
     * 序列化时值用小写的字符串
     */
    ENUM_LOWERCASE_STRING(Usage.Serialization),
    /**
     * 序列化时支持GSON的SerializedName和Expose注解   已全部默认添加
     */
    SUPPORT_GSON_ANNOTATION(Usage.Serialization),
    /**
     * 反序列化时，支持没有无参构造  非报错不添加，已动态判断
     */
    SUPPORT_NO_DEFAULT_CONSTRUCT(Usage.Deserialization),
    /**
     * 序列化和反序列化时数字类型是否需要转成字符串类型
     */
    NUMERIC_AS_STRING(Usage.All),
    /**
     * 序列化时map是否按照key正序排序
     */
    ORDER_MAP_BY_KEYS(Usage.Serialization);

    private static final long serialVersionUID = GlobalEnv.SerialVersionUID;

    private final Usage usage;

    private enum Usage {
        Serialization, Deserialization, All
    }

    Feature(Usage usage) {
        this.usage = usage;
    }

    private Usage getUsage() {
        return usage;
    }

    public static EnumSet<Feature> featureEnumSet(Feature... features) {
        return features.length == 0 ? EnumSet.noneOf(Feature.class) : EnumSet.copyOf(Arrays.asList(features));
    }

    private static final Logger logger = LoggerFactory.getLogger(Feature.class);

    public static EnumSet<Feature> removeConflictingFeatures(EnumSet<Feature> enumSet) {
        String orig = enumSet.toString();
        Map<String, Set<Feature>> remove = new HashMap<String, Set<Feature>>() {{
            put("EnumStringAndIndex", new HashSet<>());
            put("EnumLowerAndUpper", new HashSet<>());
        }};
        AtomicBoolean conflict = new AtomicBoolean(false);
        enumSet.removeIf(e -> {
            if ((e.equals(Feature.ENUM_UPPERCASE_STRING) || e.equals(Feature.ENUM_LOWERCASE_STRING)) && enumSet.contains(Feature.ENUM_INDEX)) {
                // 枚举值转换成字符串和数字，保留数字属性
                remove.get("EnumStringAndIndex").add(e);
                conflict.set(true);
                return true;
            } else if (e.equals(Feature.ENUM_UPPERCASE_STRING) && enumSet.contains(Feature.ENUM_LOWERCASE_STRING)) {
                // 枚举值大小写同时存在保留小写
                remove.get("EnumLowerAndUpper").add(e);
                conflict.set(true);
                return true;
            } else {
                return false;
            }
        });
        StringBuilder stringBuilder = new StringBuilder();
        if (!remove.get("EnumStringAndIndex").isEmpty()) {
            stringBuilder.append("枚举值的字符串属性和序列属性冲突, 移除: ").append(remove.get("EnumStringAndIndex"));
        }
        if (!remove.get("EnumLowerAndUpper").isEmpty()) {
            stringBuilder.append("枚举值的大写和小写属性冲突, 移除: ").append(remove.get("EnumLowerAndUpper"));
        }
        if (conflict.get()) logger.debug("{} {}", orig, stringBuilder);
        return enumSet;
    }
}
